package com.vshop.service.alast.impl;

import com.alibaba.fastjson.JSON;
import com.vshop.config.dto.ResultDataDto;
import com.vshop.config.dto.StringOutputConstant;
import com.vshop.entity.agatewaytobeijing.querydevice.beijing.response.DevicePackageOrder;
import com.vshop.entity.agatewaytobeijing.querydevice.beijing.response.QueryDeviceData;
import com.vshop.entity.agatewaytobeijing.querydevice.beijing.response.ResponseQueryDevice;
import com.vshop.entity.agatewaytobeijing.querydeviceorder.response.ResponseQueryDeviceOrder;
import com.vshop.entity.agatewaytobeijing.querypartnercode.response.ResponseQueryPartnerByDeviceId;
import com.vshop.entity.alast.common.*;
import com.vshop.entity.alast.homepage.request.RequestUnifiedHomePage;
import com.vshop.entity.alast.homepage.response.PageDisplay;
import com.vshop.entity.alast.homepage.response.ResponseUnifiedHomePage;
import com.vshop.entity.alast.multiple.order.request.MultipleDeviceOrder;
import com.vshop.entity.alast.multiple.order.request.RequestMultipleOrder;
import com.vshop.entity.alast.multiple.order.response.ResponseMultipleOrder;
import com.vshop.entity.alast.multiple.serviceplan.request.RequestMultipleServicePlanPage;
import com.vshop.entity.alast.multiple.verify.request.RequestMultipleVerify;
import com.vshop.entity.alast.multiple.verify.response.ResponseMultipleVerify;
import com.vshop.entity.alast.single.autorenewal.cancel.request.RequestCancelAutoRenewalRecord;
import com.vshop.entity.alast.single.autorenewal.query.request.RequestQueryAutoRenewalRecord;
import com.vshop.entity.alast.single.autorenewal.query.response.ResponseQueryAutoRenewalRecord;
import com.vshop.entity.alast.single.autorenewal.reasonforcancel.request.RequestReasonForCancel;
import com.vshop.entity.alast.single.clickgiftbox.request.RequestClickGiftBox;
import com.vshop.entity.alast.single.order.request.RequestSingleOrder;
import com.vshop.entity.alast.single.order.response.ResponseSingleOrder;
import com.vshop.entity.alast.single.querydata.request.RequestQueryData;
import com.vshop.entity.alast.single.querydata.response.ResponseQueryData;
import com.vshop.entity.alast.single.queryorder.request.RequestSingleQueryOrder;
import com.vshop.entity.alast.single.queryorder.response.PartnerPackageOrderList;
import com.vshop.entity.alast.single.queryorder.response.ResponseSingleQueryOrder;
import com.vshop.entity.alast.single.queryordersbystatus.request.RequestQueryOrdersByStatus;
import com.vshop.entity.alast.single.queryordersbystatus.response.ResponseQueryOrdersByStatus;
import com.vshop.entity.alast.single.serviceplan.request.RequestSingleServicePlanPage;
import com.vshop.entity.alast.single.subscribe.sub.request.RequestMailSubscribe;
import com.vshop.entity.alast.single.subscribe.subornot.request.RequestMailSubscribedOrNot;
import com.vshop.entity.alast.single.subscribe.subornot.response.ResponseMailSubscribedOrNot;
import com.vshop.entity.alast.single.transactionhistory.request.RequestMyTransactionHistory;
import com.vshop.entity.alast.single.transactionhistory.response.ResponseMyTransactionHistory;
import com.vshop.entity.alast.single.verify.request.RequestSingleVerify;
import com.vshop.entity.alast.single.verify.response.ResponseSingleVerify;
import com.vshop.entity.aspecial.common.PartnerSpecialDeviceLifecycle;
import com.vshop.entity.comentity.UserEmailAndDeviceSubscribeInfo;
import com.vshop.entity.requestinterface.Constant;
import com.vshop.mapper.alast.LogicProcessesMapper;
import com.vshop.service.PartnerInfoService;
import com.vshop.service.agatewaytobeijing.GatewayToBeijingService;
import com.vshop.service.agatewaytobeijing.GatewayToIotService;
import com.vshop.service.alast.LogicProcessesService;
import com.vshop.service.impl.PurchaseLogicService;
import com.vshop.utils.Md5Encrypt;
import com.vshop.utils.ParameterValidationUtil;
import com.vshop.utils.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * 所有的业务逻辑处理实现类
 *
 * @author lm
 * @date 2020/6/9 10:00
 */

@Service
@Slf4j
public class LogicProcessesServiceImpl implements LogicProcessesService {
    /**
     * 操作数据库的mapper
     */
    @Resource
    private LogicProcessesMapper logicMapper;
    /**
     * 引用了跟订购逻辑有关系的业务类：这边主要实现查询套餐是否为赠送套餐
     */
    @Autowired
    PurchaseLogicService purchaseService;
    /**
     * 引用跟企业相关的业务类
     */
    @Autowired
    PartnerInfoService partnerService;
    /**
     * 引用公用方法
     */
    @Autowired
    LogicAssistService assistService;
    /**
     * 请求网关的服务类
     */
    @Autowired
    GatewayToBeijingService toBeijingService;
    /**
     * 请求支付网关的服务类
     */
    @Autowired
    GatewayToIotService toGatewayService;
    /**
     * 时间格式化公用参数df 领科深圳的系统一般时间格式
     */
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    /**
     * 北京查询订单响应的 订购日期的一般时间格式
     */
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
    /**
     * 北京查询订单响应的 启用日期，计划截止日期的一般时间格式
     */
    SimpleDateFormat sd = new SimpleDateFormat("yyyyMMdd");


    /**
     * 统一入口：首页接口
     * 必须有个partnerCode传上来，如果前端链接上面没有的话，默认为 P000270
     * 1，先去匹配渠道的方案，如果这个时候已经匹配到方案一，方案二或者方案三，就直接根据返回的链接或提示该提示该跳转跳转
     * 2，然后去匹配方案对应的语言配置，如果匹配到方案四需要展示首页的时候根据返回的语言文案展示
     * 3，如果返回无字段或者为空时前端需要启用默认的页面设计
     * <p>
     * 返回格式是：{"data":{},"message":"string","operateCode":"string"},ResponseUnifiedHomePage是data部分
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto homePage(RequestUnifiedHomePage request) {

        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }

        log.info("统一入口：homePage首页请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getUrl()) ||
                StringUtils.isBlank(request.getSign()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getLanguageCode())) {
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }

        //先判断统一处理的结果：
        String result = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(result);
        if (!b0) {
            return ResultDataDto.addOperationFailure(result);
        }

        //参数没有问题现在就去把把访问记录记下来：
        assistService.storageHomePageRecord(request);

        //现在开始根据partnerCode匹配方案和文案
        List<PartnerConfigContent> configList = logicMapper.queryPlan(request.getPartnerCode());
        ResponseUnifiedHomePage response = null;

        boolean b1 = null != configList && !configList.isEmpty();
        if (!b1) {
            //如果当前渠道查询不到有正在使用的方案，就一切按照默认领科的情况
            log.info("【统一入口首页】渠道编码没有新建方案或者没有匹配到正在使用的方案,提示使用默认配置");
            return ResultDataDto.addOperationFailure(msg.getNotConfig());
        }

        //查询到了方案就遍历出结果
        for (PartnerConfigContent config : configList) {
            //这边判断下请求的语言是不是在方案语言中
            Integer c = logicMapper.queryLanguageCodeOrNot(config.getPartnerCode(), config.getConfigType(), config.getPlanCode(), languageCode);

            List<PartnerConfigLang> langList = logicMapper.queryLangType(request.getPartnerCode(), config.getConfigType(), config.getPlanCode());
            List<PageDisplay> displayList = new ArrayList<>();

            boolean b2 = null != langList && !langList.isEmpty();
            //如果语言配置什么的没有取到，就一切按照默认领科的情况
            if (!b2) {
                log.info("【统一入口首页】未匹配到方案对应的语言配置,提示使用默认配置");
                return ResultDataDto.addOperationFailure(msg.getNotConfigLang());
            }

            //单纯页面内容信息返回
            PageDisplay display = null;
            for (PartnerConfigLang lang : langList) {
                display = new PageDisplay();
                display.setLanguageCode(lang.getLanguageCode());
                display.setLanguageName(assistService.setLanguageName(lang.getLanguageCode()));
                display.setLanguagePriority(lang.getLanguagePriority());
                display.setWelcomeLang(lang.getWelcomeLang());
                display.setPopupContent(lang.getPopupContent());
                displayList.add(display);
            }

            //首页方案信息装配返回
            response = new ResponseUnifiedHomePage();
            //语言是当前企业能够匹配上的一种语言
            if (c >= 1) {
                response.setMatchCode("1");
            } else {
                response.setMatchCode("0");
            }
            response.setPartnerCode(config.getPartnerCode());
            response.setPlanType(config.getConfigType());
            response.setPcBgimg(config.getPcBgimg());
            response.setPhBgimg(config.getPhBgimg());
            response.setLinkURL(config.getLinkURL());
            response.setPageDisplay(displayList);
        }
        log.info("统一入口：homePage首页响应：" + JSON.toJSONString(response));
        return ResultDataDto.addOperationSuccess().setData(response);
    }

    /**
     * 统一入口：点击'Multiple'按钮之后先告诉后端请求的动作
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto multiple(RequestUnifiedHomePage request) {

        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("统一入口：Multiple接口请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) || StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getUrl()) ||
                StringUtils.isBlank(request.getSign()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getLanguageCode())) {
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }

        //先判断统一处理的结果：
        String result = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(result);
        if (!b0) {
            return ResultDataDto.addOperationFailure(result);
        }
        //如果验证参数没有问题就把访问记录记下来：
        assistService.storageMultipleRecord(request);
        log.info("【统一入口:Multiple】成功返回");
        return ResultDataDto.addOperationSuccess();

    }

    /**
     * Single模式卡片验证接口：
     * 1，验证卡片的有效性。
     * 2，验证卡片企业归属。
     * 3，验证卡片是否在除“废旧回收期”和“内部库存期”内。
     * 4，验证卡片归属企业的方案
     * 返回格式是：{"data":{},"message":"string","operateCode":"string"},ResponseSingleVerify是data部分
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto singleVerify(RequestSingleVerify request) {
        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);
        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【Single模式：单卡验证】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getLanguageCode()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode())) {
            log.info("【Single模式：单卡验证】请求不合法：" + JSON.toJSONString(ResultDataDto.addOperationFailure(msg.getInvalidParam())));
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }
        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }
        //先判断统一处理的结果：
        String result = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(result);
        if (!b0) {
            return ResultDataDto.addOperationFailure(result);
        }
        //验证通过才能继续往下执行
        ResponseSingleVerify response = null;
        List<PartnerConfigContent> configList = null;

        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");
        //归属领科的卡片必须要经过验证
        if (StringOutputConstant.CODE_ZERO.equals(request.getMark())) {
            log.info("是领科的卡片mark值是：" + request.getMark() + ";企业是：" + request.getPartnerCode());
            //判断卡片是否有效：1，是不是领科的卡，2，是不是不在“废旧回收期”和“内部库存期”内。
            ResponseQueryPartnerByDeviceId partner = toBeijingService.queryPartnerCode(deviceCode);
            if (partner != null) {
                boolean b1 = StringUtils.isNotBlank(partner.getCode()) && StringUtils.isNotBlank(partner.getMessage()) && Constant.RET_CODE_0000.equals(partner.getCode()) && null != partner.getData();
                //返回的数据要么为空，要么有误，要么返回程序有问题
                if (!b1) {
                    log.info("【iccId验证】查询渠道编码返回有误提示；请输入有效的iccId");
                    return ResultDataDto.addOperationFailure(msg.getResPartnerException());
                }
                //返回看似没有问题，但是返回的渠道编码却不合法或者0（领之飞自己）
                if (StringUtils.isBlank(partner.getData().getPartner_code()) || StringOutputConstant.CODE_ZERO.equals(partner.getData().getPartner_code())) {
                    log.info("【iccId验证】系领之飞卡提示:无效卡片");
                    return ResultDataDto.addOperationFailure(msg.getInvalidCard());
                }
                //如果以上步骤都没有问题证明至少是领科出的卡没有错，我们继续用获得的企业编码去做更多的查询
                String secret = partnerService.getSecretByPartnerCode(partner.getData().getPartner_code());
                if (StringUtils.isBlank(secret)) {
                    log.info("【iccId验证】" + partner.getData().getPartner_code() + ";当前企业secret过期或没有提示：联系我们");
                    return ResultDataDto.addOperationFailure(msg.getInvalidSecret());
                }
                //如果以上都还是没有问题，现在查询下设备的状态，为了屏蔽掉在内部库存期或废弃回收期内的卡片，不让这类卡片订购套餐。
                ResponseQueryDevice device = toBeijingService.queryDevice(deviceCode, partner.getData().getPartner_code(), secret);
                if (null != device) {
                    boolean b2 = StringUtils.isNotBlank(device.getCode()) && StringUtils.isNotBlank(device.getMessage()) && Constant.RET_CODE_0000.equals(device.getCode()) && null != device.getData();
                    if (!b2) {
                        log.info("【iccId验证】查询设备信息返回有误：" + device.getMessage() + "提示：输入有效的iccId");
                        return ResultDataDto.addOperationFailure(msg.getResPartnerException());
                    }
                    //如果查询结果返回还是没有问题，那么我们现在来屏蔽掉在内部库存期或废弃回收期内的卡片，不让这类卡片订购套餐。
                    QueryDeviceData tr = device.getData();
                    //如果卡片在内部库存期或废弃回收期内内，表明卡片过期了，不允许Top-up
                    boolean b3 = StringUtils.isBlank(tr.getLifecycle()) || "null".equalsIgnoreCase(tr.getLifecycle()) ||
                            (StringUtils.isNotBlank(tr.getLifecycle()) && (tr.getLifecycle().equals(StringOutputConstant.CODE_FOUR) || tr.getLifecycle().equals(StringOutputConstant.CODE_FIVE)));
                    if (b3) {
                        log.info("【iccId验证】SIM卡已过期");
                        return ResultDataDto.addOperationFailure(msg.getExpiredSimCard());
                    }
                    //走这边标识卡片没有过期，不管查询到的渠道编码是不是跟请求上来的一致，我们都用新的渠道编码去做覆盖然后继续去查询当前企业是否具有正在使用的某种方案
                    configList = logicMapper.queryPlan(partner.getData().getPartner_code());

                } else {
                    log.info("【iccId验证】查询设备响应有误提示；响应异常");
                    return ResultDataDto.addOperationFailure(msg.getResException());
                }
            } else {
                log.info("【iccId验证】查询渠道编码响应有误提示：响应异常");
                return ResultDataDto.addOperationFailure(msg.getResException());
            }
        } else {
            //没有领科标识的走另外的验证模式,如果不是领科标识的卡片,partnerCode是唯一标识，不可有误
            log.info("不是领科的卡片mark值是：" + request.getMark() + ";企业是：" + request.getPartnerCode());
            configList = logicMapper.queryPlan(request.getPartnerCode());
        }

        //现在开始是公共的验证：从方案开始验证，不管是不是领科卡片都需要被验证方案和方案语言
        if (null == configList || configList.isEmpty()) {
            log.info("卡片是：" + request.getDeviceCode() + "：没有可用方案提示：联系我们");
            return ResultDataDto.addOperationFailure(msg.getNotInUsePlan());
        }

        List<PartnerConfigLang> langList = null;
        //通过方案去遍历方案对应的语言欢迎语那些：
        for (PartnerConfigContent config : configList) {
            //拿到方案标识去查询当前企业此方案对应的语言配置
            langList = logicMapper.queryLangType(config.getPartnerCode(), config.getConfigType(), config.getPlanCode());
        }

        if (null == langList || langList.isEmpty()) {
            log.info("【iccId验证】归属企业方案语言有误提示：联系我们");
            return ResultDataDto.addOperationFailure(msg.getNotInUsePlan());
        }

        //统一返回
        response = assistService.responseSingleVerify(configList, deviceCode, request.getLanguageCode());
        //把这次有效的访问记录下来
        assistService.storageDeviceLoginRecord(request);

        //卡片成功返回
        log.info("【Single模式：单卡验证】成功响应：" + JSON.toJSONString(response));
        return ResultDataDto.addOperationSuccess().setData(response);
    }


    /**
     * Single模式：套餐列表页面接口：
     * 1，当前企业卡片可购套餐允许展示re.showStatus='1'；
     * 2，当前企业上架的套餐中存在第1步中的套餐编码p.packageCode = re.packageCode AND p.servicePlanStatus = '2'
     * 3, 当前请求的语言作为一个参数，如果一个企业某个语言的套餐上架好几个也是允许的
     * <p>
     * 返回格式是：{"data":{},"message":"string","operateCode":"string"},ResponsePartnerServicePlan是data部分
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto singleServicePlanPage(RequestSingleServicePlanPage request) {

        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【Single模式：套餐列表】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) || null == request.getArea() ||
                StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode()) || StringUtils.isBlank(request.getLanguageCode())) {
            log.info("【Single模式：套餐列表】请求不合法：" + JSON.toJSONString(ResultDataDto.addOperationFailure(msg.getInvalidParam())));
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }

        //先判断统一处理的结果：
        String result = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(result);
        if (!b0) {
            return ResultDataDto.addOperationFailure(result);
        }

        //先确定给这个企业匹配什么语言的套餐
        String languageType = assistService.queryLanguageType(request.getPartnerCode(), request.getLanguageCode());
        // 根据partnerIndex分别去分库里面取相应的卡片与套餐对应关系的数据：
        Integer partnerIndex = Integer.parseInt(partnerService.getPartnerIndex(request.getPartnerCode()));
        if (StringUtils.isBlank(languageType) || null == partnerIndex) {
            log.info("languageType查询失误或者partnerIndex查询有误提示：程序异常");
            return ResultDataDto.addOperationFailure(msg.getResException());
        }

        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");

        //预备套餐列表接收数据库取到得我套餐列表
        List<PartnerServicePlan> planList = null;

        //归属领科卡片
        if (StringOutputConstant.CODE_ZERO.equalsIgnoreCase(request.getMark())) {
            //用这个方案去匹配套餐
            planList = assistService.queryServicePlanCode(partnerIndex, request.getPartnerCode(), deviceCode, languageType, "0");
        }
        //不归属领科卡片的处理方式，直接去数据库匹配出服务费套餐
        if (StringOutputConstant.CODE_ONE.equalsIgnoreCase(request.getMark()) && StringUtils.isNotBlank(request.getArea())) {
            //直接去partner_service_plan_t拿到某个企业的服务费套餐,tags=2是外部卡在领科代收服务费的套餐标识
            planList = assistService.queryServiceFeePlan(request.getPartnerCode(), languageType, "2", request.getArea());
        }

        //如果没有匹配到套餐列表，直接返回Not Service Plan
        if (null == planList || planList.isEmpty()) {
            log.info("Single模式：未匹配到套餐列表提示：无可购买套餐服务");
            return ResultDataDto.addOperationFailure(msg.getNotInUseService());
        }

        List<PartnerServicePlanSpecPrice> priceList = null;
        //遍历套餐列表取新建套餐规格和价格
        for (PartnerServicePlan pl : planList) {
            //1,取出套餐编码去匹配规格和价格
            priceList = logicMapper.querySpecPrice(pl.getPartnerCode(), pl.getPackageCode(), pl.getServicePlanCode(), "1");
        }

        //如果取到的套餐对应的规格和价格为空，直接提示：无可购买套餐服务
        if (null == priceList || priceList.isEmpty()) {
            log.info("Single模式：未匹配到套餐规格和价格不允许展示提示：无可购买套餐服务（Not Specification And Price）");
            return ResultDataDto.addOperationFailure(msg.getNotInUseService());
        }
        //套餐列表返回
        return assistService.responseServicePlan(planList, request.getPartnerCode(), "1");
    }

    /**
     * Single模式：查询正在使用，未启用的订单：
     * <p>
     * 返回格式是：{"data":{},"message":"string","operateCode":"string"},ResponseSingleQueryOrder是data部分
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto singleQueryOrder(RequestSingleQueryOrder request) {

        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }

        log.info("【Single模式：查询订单】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode()) || StringUtils.isBlank(request.getLanguageCode())) {
            log.info("【Single模式：查询订单】请求不合法：" + ResultDataDto.addOperationFailure(msg.getInvalidParam()));
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }
        //先判断统一处理的结果：
        String result = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(result);
        if (!b0) {
            return ResultDataDto.addOperationFailure(result);
        }
        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");
        //验证通过才能继续往下执行订单返回
        List<PartnerPackageOrderList> orderList = new ArrayList<>();

        //归属领科卡片
        if (StringOutputConstant.CODE_ZERO.equalsIgnoreCase(request.getMark())) {
            //我们继续用获得的企业编码去做更多的查询
            String secret = partnerService.getSecretByPartnerCode(request.getPartnerCode());
            if (StringUtils.isBlank(secret)) {
                log.info("【Single模式查询订单】" + request.getPartnerCode() + ";当前企业secret有误请联系管理员！");
                return ResultDataDto.addOperationFailure(msg.getInvalidSecret());
            }
            //说明接口从2.0更新到3.0了
            ResponseQueryDeviceOrder or = toBeijingService.queryDeviceOrder(deviceCode, "", "", "", request.getPartnerCode(), secret);
            if (null == or || or.getData() == null) {
                log.info("订单查询为空");
                return ResultDataDto.addOperationSuccess(msg.getBuyNow());
            }
            for (com.vshop.entity.agatewaytobeijing.querydeviceorder.response.DevicePackageOrder data : or.getData().getPackageOrder()) {
                //直接匹配符合条件的订单，不符合就继续循环
                boolean b2 = StringUtils.isNotBlank(data.getOrderStatus()) && StringUtils.isNotBlank(data.getPackageCode()) && (data.getOrderStatus().equals(StringOutputConstant.CODE_ONE) || data.getOrderStatus().equals(StringOutputConstant.CODE_TWO));
                if (b2) {
                    PartnerPackageOrderList order = new PartnerPackageOrderList();
                    //有未启用或者正在使用个的套餐的前提再去遍历是不是赠送套餐
                    //拿着data.getPackageCode()去数据库查询看看有没有这个赠送套餐的套餐编码
                    Integer c = purchaseService.queryGiveDateOrNot(data.getPackageCode());
                    //如果传c>=1说明未启用的订单或者正在使用的订单是赠送套餐
                    boolean b3 = c >= 1;
                    //如果有存在订单的套餐是赠送套餐，直接终止本次循环跳出去
                    if (b3) {
                        continue;
                    } else {
                        /*现在去数据库里面匹配售卖的套餐名称*/
                        String servicePlanShowName = logicMapper.queryServicePlanShowName(request.getPartnerCode(), data.getPackageCode(), request.getLanguageCode());

                        if (StringUtils.isNotBlank(servicePlanShowName)) {
                            order.setServicePlanShowName(servicePlanShowName);
                        } else {
                            order.setServicePlanShowName(assistService.setServicePlanShowName(request.getLanguageCode()));
                        }
                    }
                    try {
                        if (StringUtils.isNotBlank(data.getExpireDate())) {
                            order.setExpireDate(new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyyMMdd").parse(data.getExpireDate())));
                            //正在使用的订单的剩余天数=理论到期时间-今天
                            order.setRemainingDays(DateUtil.remainingDays(new SimpleDateFormat("yyyyMMdd").parse(data.getExpireDate()), "1"));
                        } else {
                            //未启用订单的订单剩余天数=订购周期X=*天
                            order.setRemainingDays(DateUtil.theoreticalDays(data.getOrderPeriod(), data.getPackageType()));
                        }
                    } catch (ParseException e) {
                        log.info("时间换算出现异常：" + e);
                    }
                    order.setOrderStatus(data.getOrderStatus());
                    order.setTime(assistService.setOrderPeriod(data.getPackageType(), data.getOrderPeriod()));
                    order.setUnit(data.getPackageType());
                    orderList.add(order);
                }
            }
        }

        //非领科卡片直接查询我们自己的订单系统就够了
        if (StringOutputConstant.CODE_ONE.equalsIgnoreCase(request.getMark())) {
            List<PartnerSpecialDeviceLifecycle> recordList = logicMapper.querySpecialOrderRecord(request.getPartnerCode(), deviceCode, request.getMark());
            if (null == recordList || recordList.isEmpty()) {
                log.info("查询不到套餐的原因有可能是程序有误，也有可能是真的不存在订单提示：没有订单，现在购买");
                return ResultDataDto.addOperationSuccess(msg.getBuyNow());
            }
            //遍历特殊设备的生命周期订单
            for (PartnerSpecialDeviceLifecycle device : recordList) {
                try {
                    PartnerPackageOrderList order = new PartnerPackageOrderList();
                    order.setServicePlanShowName(device.getServicePlanShowName());
                    if (StringUtils.isNotBlank(device.getOrderExpireDate())) {
                        order.setExpireDate(new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(device.getOrderExpireDate())));
                        //正在使用的订单的剩余天数=理论到期时间-今天
                        order.setRemainingDays(DateUtil.remainingDays(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(device.getOrderExpireDate()), "2"));
                    } else {
                        //未启用订单的订单剩余天数=订购周期X=*天
                        order.setRemainingDays(DateUtil.theoreticalDays(device.getOrderPeriod(), device.getPackageType()));
                    }
                    order.setOrderStatus(device.getStatus());
                    order.setTime(assistService.setOrderPeriod(device.getPackageType(), device.getOrderPeriod()));
                    order.setUnit(device.getPackageType());
                    orderList.add(order);
                } catch (ParseException e) {
                    log.info("截止时间换算出现异常：" + e);
                }
            }
        }
        //返回
        ResponseSingleQueryOrder response = new ResponseSingleQueryOrder();
        response.setPartnerCode(request.getPartnerCode());
        response.setDeviceCode(deviceCode);
        response.setOrderList(orderList);
        log.info("【Single模式查询订单】成功响应：" + JSON.toJSONString(response));
        return ResultDataDto.addOperationSuccess().setData(response);
    }

    /**
     * Single模式：下单接口：
     * <p>
     * 返回格式是：{"data":{},"message":"string","operateCode":"string"},ResponseSingleOrder是data部分
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto singleOrder(RequestSingleOrder request) {

        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【Single模式：下单】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode()) || StringUtils.isBlank(request.getOrderNo()) || StringUtils.isBlank(request.getPayId()) ||
                StringUtils.isBlank(request.getPayAmount()) || StringUtils.isBlank(request.getPayCurrency()) || StringUtils.isBlank(request.getPackageCode()) || StringUtils.isBlank(request.getServicePlanCode()) ||
                StringUtils.isBlank(request.getServicePlanShowName()) || StringUtils.isBlank(request.getOrderPeriod()) || null == request.getRequestOrderId() || StringUtils.isBlank(request.getAutoRenewal())) {
            log.info("【Single模式：下单】请求不合法：" + ResultDataDto.addOperationFailure(msg.getInvalidParam()));
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }

        /*先判断统一处理的结果*/
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equalsIgnoreCase(re);
        if (!b0) {
            log.info("partnerCode,terminal和mark参数其中一个有误");
            return ResultDataDto.addOperationFailure(re);
        }

        /*格式化一下iccId，去掉所有的空格，首和尾以及中间*/
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");

        /*先做下重复请求验证，对于同一个卡片deviceCode同一个套餐packageCode+servicePlanCode，同一个支付单号payId，同一个orderNo我们认为是唯一的请求，不同的请求支付单号必须刷新*/
        Integer count = logicMapper.queryOrderCount(request.getPartnerCode(), deviceCode, request.getPackageCode(), request.getServicePlanCode(), request.getPayId(), request.getOrderNo());
        if (count > 0) {
            log.info("Single下单失败：重复的下单请求提示：重复的下单请刷新");
            return ResultDataDto.addOperationFailure(msg.getRepeatOrder());
        }

        /*这边要对属于领科自己的卡片去验证，如果卡片不属于领科mark=1就不需要去验证*/
        if (StringOutputConstant.CODE_ZERO.equals(request.getMark())) {
            //验证deviceCode卡片的有效性,如果有错误直接使用msg提示信息返回
            String result = assistService.validationDeviceCode(deviceCode, msg);
            if (!StringOutputConstant.CODE_SUCCESS.equalsIgnoreCase(result)) {
                return ResultDataDto.addOperationFailure(result);
            }
        }

        //验证一下前端传上来的金额是不是符合规则的
        boolean bVerify = !ParameterValidationUtil.isPositive(request.getPayAmount()) || (!"USD".equalsIgnoreCase(request.getPayCurrency()) && !"CNY".equalsIgnoreCase(request.getPayCurrency()) && !"EUR".equalsIgnoreCase(request.getPayCurrency()));
        if (bVerify) {
            log.info("Single下单失败：payAmount支付金额或者payCurrency不符合规则");
            return ResultDataDto.addOperationFailure(msg.getInvalidAmount());
        }

        /*根据已有的企业和套餐编码去查询原始套餐表，确认套餐信息无误,需要验证的也是套餐的最大订购周期和最小订购周期：maxOrderPeriod和minOrderPeriod*/
        PartnerPackage packages = logicMapper.queryPackage(request.getPartnerCode(), request.getPackageCode());
        if (null == packages) {
            log.info("Single下单失败：企业下面不存在此原始套餐，或者请求内参数有误提示：无权限购买此原始套餐");
            return ResultDataDto.addOperationFailure(msg.getNoRightOrder());
        }

        //1,这边要重点验证一下orderPeriod的值，只能是大于1的正整数,当套餐的最小可够数值和最大可够数值相等时，orderPeriod不等于这个值的时候
        boolean b4 = (!ParameterValidationUtil.isInteger(request.getOrderPeriod())) || (packages.getMinOrderPeriod().equals(packages.getMaxOrderPeriod()) && !request.getOrderPeriod().equals(packages.getMinOrderPeriod()));
        if (b4) {
            log.info("Single下单失败：orderPeriod订购周期不符合规则");
            return ResultDataDto.addOperationFailure(msg.getInvalidOrderPeriod());
        }

        /*比较一下下单请求中的servicePlanCode与orderPeriod和autoRenewal是否匹配，匹配就用传的值，不匹配就直接不让下单了，这样能保证用户始终能正常订购到我们发布的产品订购周期*/
        PartnerServicePlanSpecPrice specPrice = logicMapper.querySpecPricedByServicePlanCode(request.getServicePlanCode(), request.getOrderPeriod(), request.getAutoRenewal());
        if (null == specPrice) {
            log.info("Single下单失败：下单的servicePlanCode与specifications和autoRenewal查不到对应的价格方案");
            return ResultDataDto.addOperationFailure(msg.getFailedOrder());
        }
        if (!request.getServicePlanShowName().equals(specPrice.getServicePlanShowName())) {
            log.info("Single下单失败：下单的servicePlanShowName的传值与价格方案中不一致");
            return ResultDataDto.addOperationFailure(msg.getFailedOrder());
        }
        if (!request.getPayAmount().equals(specPrice.getDiscountPriceUSD()) && !request.getPayAmount().equals(specPrice.getDiscountPriceCNY())) {
            log.info("Single下单失败：下单的payAmount的传值与价格方案中不一致");
            return ResultDataDto.addOperationFailure(msg.getFailedOrder());
        }

        //把原始套餐的信息取出来用于订单入库时使用,验证流程结束，现在可以确定当前卡片是有效的，订单请求也没有重复，现在开始在数据库下单
        ServicePlanOrderRecord record = new ServicePlanOrderRecord();
        record.setPayId(request.getPayId());
        record.setRequestOrderId(request.getRequestOrderId());
        record.setDeviceCode(deviceCode);
        record.setOrderNo(request.getOrderNo());
        record.setPartnerCode(request.getPartnerCode());
        record.setPartnerName(packages.getPartnerName());
        record.setServicePlanShowName(request.getServicePlanShowName());
        record.setServicePlanCode(request.getServicePlanCode());
        record.setPackageName(packages.getPackageName());
        record.setPackageCode(request.getPackageCode());
        record.setPackageType(packages.getPackageType());
        record.setOrderPeriod(request.getOrderPeriod());
        record.setPayAmount(request.getPayAmount());
        record.setPayCurrency(request.getPayCurrency());
        record.setTerminal(request.getTerminal());
        record.setMark(request.getMark());
        record.setPayMode(request.getAutoRenewal());

        Integer co = logicMapper.buildOrderRecord(record);
        /*下单失败，入数据库失败*/
        if (co == 0) {
            log.info("Single下单失败：数据库写入数据失败");
            return ResultDataDto.addOperationFailure(msg.getFailedOrder());
        }
        /*下单成功:响应*/
        ResponseSingleOrder response = new ResponseSingleOrder();
        response.setPartnerCode(request.getPartnerCode());
        response.setDeviceCode(deviceCode);
        response.setOrderNo(request.getOrderNo());
        response.setPayId(request.getPayId());
        log.info("【Single模式下单】成功响应：" + JSON.toJSONString(response));
        return ResultDataDto.addOperationSuccess().setData(response);
    }

    /**
     * 方案一，流量查询接口：
     * <p>
     * 返回格式是：{"data":{},"message":"string","operateCode":"string"},ResponseQueryData是data部分
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto queryData(RequestQueryData request) {

        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }

        log.info("【方案一流量查询】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode()) || StringUtils.isBlank(request.getLanguageCode())) {
            log.info("【方案一流量查询】请求不合法：" + ResultDataDto.addOperationFailure(msg.getInvalidParam()));
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }

        //先判断统一处理的结果：
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equalsIgnoreCase(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }

        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");

        //领科的卡片做流量查询操作
        if (StringOutputConstant.CODE_ZERO.equalsIgnoreCase(request.getMark())) {
            //如果以上步骤都没有问题证明至少是领科出的卡没有错，我们继续用获得的企业编码去做更多的查询
            String secret = partnerService.getSecretByPartnerCode(request.getPartnerCode());
            if (StringUtils.isBlank(secret)) {
                log.info("【方案一流量查询】" + request.getPartnerCode() + ";当前企业secret有误请联系管理员！");
                return ResultDataDto.addOperationFailure(msg.getInvalidSecret());
            }

            //去数据库拿出这个企业已启用的方案需要展示的字段，取出来是个String字符串，把字符串用逗号分开
            String showContent = logicMapper.queryShowContent(request.getPartnerCode());
            ResponseQueryData response = null;

            //如果以上都还是没有问题，现在查询下设备的状态，为了屏蔽掉在内部库存期或废弃回收期内的卡片，不让这类卡片订购套餐。
            ResponseQueryDevice device = toBeijingService.queryDevice(deviceCode, request.getPartnerCode(), secret);

            if (null != device) {
                boolean b2 = StringUtils.isNotBlank(device.getCode()) && null != device.getData() && Constant.RET_CODE_0000.equals(device.getCode());
                if (!b2) {
                    response = assistService.responseShowContent(showContent, request.getPartnerCode());
                    log.info("【方案一流量查询】英文查询设备信息返回有误：" + device.getMessage() + ";" + JSON.toJSONString(response));
                    return ResultDataDto.addOperationSuccess().setData(response);
                }

                QueryDeviceData tr = device.getData();

                boolean b3 = StringUtils.isNotBlank(tr.getDevice_id()) && StringUtils.isNotBlank(tr.getLifecycle()) && "2".equals(tr.getLifecycle()) && null != tr.getPackage_order();
                if (!b3) {
                    response = assistService.responseShowContent(showContent, request.getPartnerCode());
                    log.info("【方案一流量查询】设备不在使用期内提示：卡片未进入使用期无流量产生" + ";" + JSON.toJSONString(response));
                    return ResultDataDto.addOperationSuccess().setData(response);
                }

                DevicePackageOrder order = tr.getPackage_order();

                boolean b4 = StringUtils.isNotBlank(order.getOrderCode()) && StringUtils.isNotBlank(order.getPackageCode()) && StringUtils.isNotBlank(order.getPackageType()) &&
                        StringUtils.isNotBlank(order.getOrderPeriod()) && StringUtils.isNotBlank(order.getActiveDate()) && StringUtils.isNotBlank(order.getExpireDate()) &&
                        StringUtils.isNotBlank(order.getBuyType());
                if (!b4) {
                    response = assistService.responseShowContent(showContent, request.getPartnerCode());
                    log.info("【方案一流量查询】正在使用的订单信息有误提示：订单无流量产生" + ";" + JSON.toJSONString(response));
                    return ResultDataDto.addOperationSuccess().setData(response);
                }

                //先确定给这个企业匹配什么语言的套餐
                String languageType = assistService.queryLanguageType(request.getPartnerCode(), request.getLanguageCode());
                //现在去数据库里面匹配售卖的套餐名称
                String servicePlanShowName = logicMapper.queryServicePlanShowName(request.getPartnerCode(), order.getPackageCode(), languageType);
                response = new ResponseQueryData();

                //根据数据库里面的字段分别去匹配并且返回
                if (StringUtils.isNotBlank(showContent)) {
                    //截取获得字符串数组
                    String[] strArray = showContent.split(",");
                    for (int i = 0; i < strArray.length; i++) {

                        if (strArray[i].equals("servicePlanShowName")) {

                            if (StringUtils.isNotBlank(servicePlanShowName)) {
                                response.setServicePlanShowName(servicePlanShowName);
                            } else {
                                response.setServicePlanShowName(assistService.setServicePlanShowName(request.getLanguageCode()));
                            }

                        } else if (strArray[i].equals("activeDate")) {
                            try {
                                if (StringUtils.isNotBlank(order.getActiveDate())) {
                                    response.setActiveDate(new SimpleDateFormat("yyyy/mm/dd").format(new SimpleDateFormat("yyyymmdd").parse(order.getActiveDate())));
                                } else {
                                    response.setActiveDate("-");
                                }
                            } catch (Exception e) {
                                log.info("转换激活时间和预计到期时间时发生了异常：" + e);
                                response.setActiveDate("-");
                            }

                        } else if (strArray[i].equals("expireDate")) {
                            try {
                                if (StringUtils.isNotBlank(order.getExpireDate())) {
                                    response.setExpireDate(new SimpleDateFormat("yyyy/mm/dd").format(new SimpleDateFormat("yyyymmdd").parse(order.getExpireDate())));
                                } else {
                                    response.setExpireDate("-");
                                }
                            } catch (Exception e) {
                                log.info("转换激活时间和预计到期时间时发生了异常：" + e);
                                response.setExpireDate("-");
                            }

                        } else if (strArray[i].equals("dataTotal")) {

                            if (StringUtils.isNotBlank(order.getFlow()) && StringUtils.isNotBlank(order.getUsedFlow())) {
                                response.setDataTotal(order.getFlow() + "MB");
                            } else {
                                response.setDataTotal("-");
                            }

                        } else if (strArray[i].equals("dataBalance")) {
                            //先算流量
                            if (StringUtils.isNotBlank(order.getFlow()) && StringUtils.isNotBlank(order.getUsedFlow())) {
                                String dataBalance = String.format("%.2f", (Double.parseDouble(order.getFlow()) - Double.parseDouble(order.getUsedFlow()) / 1024)) + "MB";
                                response.setDataBalance(dataBalance);
                            } else {
                                response.setDataBalance("-");
                            }

                        }

                        //用于协助显示单位的字段：
                        if (StringUtils.isNotBlank(order.getPackageType())) {
                            response.setPackageType(order.getPackageType());
                        } else {
                            response.setPackageType("-");
                        }
                    }

                } else {
                    //数据库没有查询到或者数组else的情况都走下面的路：
                    //套餐名称
                    if (StringUtils.isBlank(servicePlanShowName)) {
                        response.setServicePlanShowName(assistService.setServicePlanShowName(request.getLanguageCode()));
                    } else {
                        response.setServicePlanShowName(servicePlanShowName);
                    }

                    //总流量，剩余流量
                    if (StringUtils.isNotBlank(order.getFlow()) && StringUtils.isNotBlank(order.getUsedFlow())) {
                        String dataBalance = String.format("%.2f", (Double.parseDouble(order.getFlow()) - Double.parseDouble(order.getUsedFlow()) / 1024)) + "MB";
                        response.setDataTotal(order.getFlow() + "MB");
                        response.setDataBalance(dataBalance);
                    } else {
                        response.setDataTotal("-");
                        response.setDataBalance("-");
                    }
                    //激活时间，到期时间
                    try {
                        if (StringUtils.isNotBlank(order.getActiveDate()) && StringUtils.isNotBlank(order.getExpireDate())) {
                            response.setActiveDate(new SimpleDateFormat("yyyy/mm/dd").format(new SimpleDateFormat("yyyymmdd").parse(order.getActiveDate())));
                            response.setExpireDate(new SimpleDateFormat("yyyy/mm/dd").format(new SimpleDateFormat("yyyymmdd").parse(order.getExpireDate())));
                        } else {
                            response.setActiveDate("-");
                            response.setExpireDate("-");
                        }
                    } catch (Exception e) {
                        log.info("转换激活时间和预计到期时间时发生了异常：" + e);
                        response.setActiveDate("-");
                        response.setExpireDate("-");
                    }

                    //用于协助显示单位的字段：
                    if (StringUtils.isNotBlank(order.getPackageType())) {
                        response.setPackageType(order.getPackageType());
                    } else {
                        response.setPackageType("-");
                    }
                }


                response.setPartnerCode(request.getPartnerCode());
                log.info("【方案一流量查询】成功响应：" + JSON.toJSONString(response));
                return ResultDataDto.addOperationSuccess().setData(response);

            } else {
                log.info("【方案一流量查询】查询设备出现问题提示：响应异常");
                return ResultDataDto.addOperationFailure(msg.getResException());
            }
        } else {
            //不归属领科的卡片不允许做查询流量操作
            log.info("【方案一流量查询】：不归属领科的卡片不允许做查询流量操作提示：无效卡片");
            return ResultDataDto.addOperationFailure(msg.getInvalidCard());
        }
    }

    /**
     * Multiple模式卡片验证接口：
     * 1，验证卡片的有效性。
     * 2，验证卡片企业归属。
     * 3，验证卡片是否在除“废旧回收期”和“内部库存期”内。
     * 4，验证卡片归属企业的方案
     * 5，两张卡对应的套餐比对是否一致
     * <p>
     * 返回格式是：{"data":{},"message":"string","operateCode":"string"},ResponseMultipleVerify是data部分
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto multipleVerify(RequestMultipleVerify request) {

        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }

        log.info("【Multiple模式：多卡验证】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getLanguageCode()) || StringUtils.isBlank(request.getPartnerCode()) ||
                StringUtils.isBlank(request.getDeviceCode1()) || null == request.getDeviceCode2()) {
            log.info("【Multiple模式：多卡验证】请求不合法：" + JSON.toJSONString(ResultDataDto.addOperationFailure(msg.getInvalidParam())));
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }

        //先判断统一处理的结果：
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equalsIgnoreCase(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }

        //不归属领科的卡片不允许做小批量操作
        if (StringOutputConstant.CODE_ONE.equals(request.getMark())) {
            log.info("【Multiple模式：多卡验证】：不归属领科的卡片不允许做小批量操作提示：无效卡片");
            return ResultDataDto.addOperationFailure(msg.getInvalidCard());
        }
        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode1 = request.getDeviceCode1().replaceAll("\\s*", "");
        String deviceCode2 = request.getDeviceCode2().replaceAll("\\s*", "");

        //验证deviceCode1 卡1的有效性
        String result = assistService.validationDeviceCode(deviceCode1, msg);
        if (!StringOutputConstant.CODE_SUCCESS.equalsIgnoreCase(result)) {
            return ResultDataDto.addOperationFailure(result);
        }
        //先判断卡片1是否有效：1，是不是领科的卡，2，是不是不在“废旧回收期”和“内部库存期”内。
        ResponseQueryPartnerByDeviceId partner = toBeijingService.queryPartnerCode(deviceCode1);

        //走这边标识卡片没有过期，不管查询到的渠道编码是不是跟请求上来的一致，我们都用新的渠道编码去做覆盖然后继续去查询当前企业是否具有正在使用的某种方案,只允许直接订购（方案4）购买套餐
        List<PartnerConfigContent> configList = logicMapper.queryPlanOrder(partner.getData().getPartner_code());
        if (null == configList || configList.isEmpty()) {
            log.info("Multiple模式【1卡】归属企业无正在使用方案的");
            return ResultDataDto.addOperationFailure(msg.getNotInUsePlan());
        }

        //先确定给这个企业匹配什么语言的套餐
        String languageType = assistService.queryLanguageType(partner.getData().getPartner_code(), request.getLanguageCode());

        // 根据partnerIndex分别去分库里面取相应的卡片与套餐对应关系的数据：
        Integer partnerIndex = Integer.parseInt(partnerService.getPartnerIndex(partner.getData().getPartner_code()));

        if (StringUtils.isBlank(languageType) || null == partnerIndex) {
            log.info("languageType查询失误或者partnerIndex查询有误");
            return ResultDataDto.addOperationFailure("Program error");
        }
        //走这里去匹配1卡拿套餐了
        List<PartnerServicePlan> planList = assistService.queryServicePlanCode(partnerIndex, partner.getData().getPartner_code(), deviceCode1, languageType, "0");

        //如果没有匹配到套餐列表，直接返回Not Service Plan
        if (null == planList || planList.isEmpty()) {
            log.info("Multiple模式【1卡】未匹配到套餐,Not Service Plan");
            return ResultDataDto.addOperationFailure(msg.getNotInUseService());
        }

        //如果有deviceCode2
        List<PartnerConfigContent> configList2 = null;
        List<PartnerServicePlan> planList2 = null;

        if (StringUtils.isNotBlank(deviceCode2)) {
            //先判断deviceCode1是不是跟deviceCode2相同，相同是不允许的
            if (deviceCode1.equals(deviceCode2)) {
                log.info("Multiple模式【iccId验证】1卡和2卡相同");
                return ResultDataDto.addOperationFailure(msg.getRepeatCard());
            }
            //验证deviceCode2 卡2的有效性
            String result2 = assistService.validationDeviceCode(deviceCode2, msg);
            if (!StringOutputConstant.CODE_SUCCESS.equalsIgnoreCase(result2)) {
                return ResultDataDto.addOperationFailure(result2);
            }

            //先判断卡片2是否有效：1，是不是领科的卡，2，是不是不在“废旧回收期”和“内部库存期”内。
            ResponseQueryPartnerByDeviceId partner2 = toBeijingService.queryPartnerCode(deviceCode2);

            //现在判断两张卡片的渠道归属是否为同一家,如果卡片不属于同一家直接返回前端
            if (!partner.getData().getPartner_code().equalsIgnoreCase(partner2.getData().getPartner_code())) {
                log.info(deviceCode1 + "：归属：" + partner.getData().getPartner_code() + "和" + partner2.getData().getPartner_code() + "两张卡片不属于同一家企业");
                return ResultDataDto.addOperationFailure(msg.getDifferentPartnerCard());
            }

            //走这边标识卡片没有过期，不管查询到的渠道编码是不是跟请求上来的一致，我们都用新的渠道编码去做覆盖然后继续去查询当前企业是否具有正在使用的某种方案,只允许直接订购（方案4）购买套餐
            configList2 = logicMapper.queryPlanOrder(partner2.getData().getPartner_code());
            if (null == configList2 || configList2.isEmpty()) {
                log.info("Multiple模式【1卡和2卡】归属企业无正在使用方案的");
                return ResultDataDto.addOperationFailure(msg.getNotInUsePlan());
            }

            //走到这里说明1卡拿到套餐了，紧接着匹配下2卡的套餐
            planList2 = assistService.queryServicePlanCode(partnerIndex, partner.getData().getPartner_code(), deviceCode2, languageType, "0");

            //如果没有匹配到套餐列表，直接返回Not Service Plan
            if (null == planList2 || planList2.isEmpty()) {
                log.info("Multiple模式【2卡】未匹配到套餐,Not Service Plan");
                return ResultDataDto.addOperationFailure(msg.getNotInUseService());
            }

            //两张卡拿到的方案不一致：
            if (!configList.equals(configList2)) {
                log.info("Multiple验证卡片：两个企业拿到的方案不一致提示：当前卡不能与上一张卡同时充值");
                return ResultDataDto.addOperationFailure(msg.getDifferentPartnerCard());
            }

            //两张卡片可购买的套餐不一致：
            if (!planList.equals(planList2)) {
                log.info("Multiple验证卡片：可够套餐列表不一致提示：当前卡不能与上一张卡同时充值");
                return ResultDataDto.addOperationFailure(msg.getDifferentPartnerCard());
            }
        }

        //走到这边不管是几张卡plan的List都是相同的，那么我们遍历planList就可以了
        Integer c = 0;
        List<PageDisplay> displayList = new ArrayList<>();

        for (PartnerConfigContent config : configList) {
            //这边判断下请求的语言是不是在方案语言中
            c = logicMapper.queryLanguageCodeOrNot(partner.getData().getPartner_code(), config.getConfigType(), config.getPlanCode(), request.getLanguageCode());

            //拿到方案标识去查询当前企业此方案对应的语言配置
            List<PartnerConfigLang> langList = logicMapper.queryLangType(partner.getData().getPartner_code(), config.getConfigType(), config.getPlanCode());

            //遍历页面语言内容
            for (PartnerConfigLang t : langList) {
                PageDisplay display = new PageDisplay();
                display.setLanguageName(assistService.setLanguageName(t.getLanguageCode()));
                display.setLanguagePriority(t.getLanguagePriority());
                display.setLanguageCode(t.getLanguageCode());
                displayList.add(display);
            }

        }

        //只有卡1的情况并且验证成功
        ResponseMultipleVerify response = new ResponseMultipleVerify();
        //语言是当前企业能够匹配上的一种语言
        if (c >= 1) {
            response.setMatchCode("1");
        } else {
            response.setMatchCode("0");
        }
        response.setPartnerCode(partner.getData().getPartner_code());
        response.setDeviceCode1(deviceCode1);
        response.setDeviceCode2(deviceCode2);
        response.setPageDisplay(displayList);

        //4，如果以上所有的情况都通过，可以返回成功。
        log.info("【Multiple模式：多卡验证】成功响应：" + JSON.toJSONString(response));
        return ResultDataDto.addOperationSuccess().setData(response);
    }

    /**
     * Multiple模式多卡片匹配可够套餐列表接口
     * <p>
     * 返回格式是：{"data":{},"message":"string","operateCode":"string"},ResponsePartnerServicePlan是data部分
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto multipleServicePlanPage(RequestMultipleServicePlanPage request) {

        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【Multiple模式：多卡片匹配套餐列表】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getLanguageCode()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode())) {
            log.info("【Multiple模式：多卡片匹配套餐列表】请求不合法：" + JSON.toJSONString(ResultDataDto.addOperationFailure(msg.getInvalidParam())));
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }

        //先判断统一处理的结果：
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equalsIgnoreCase(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }

        //不归属领科的卡片不允许做小批量操作
        if (StringOutputConstant.CODE_ONE.equals(request.getMark())) {
            log.info("【Multiple模式：多卡片匹配套餐列表】：不归属领科的卡片不允许做小批量操作提示：无效卡片");
            return ResultDataDto.addOperationFailure(msg.getInvalidCard());
        }
        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");

        try {
            //将字符串用逗号分隔开
            String[] codeArray = deviceCode.split(",");
            //由于HashSet实现了set接口，所以它不允许集合中有重复的值，在调用add方法时，如果插入了重复值，会返回false,因此方法返回false时就是出现了重复值
            if (!assistService.checkIsRepeat(codeArray)) {
                log.info("【Multiple模式：多卡片匹配套餐列表】：请求的卡片列表存在重复卡片");
                return ResultDataDto.addOperationFailure(msg.getRepeatCard());
            }

            //我们应该想在外面验证两张卡片的套餐是不是一样的
            if (StringUtils.isBlank(codeArray[0])) {
                log.info("deviceCode参数可能为空或者没传");
                return ResultDataDto.addOperationFailure(msg.getResPartnerException());
            }

            String deviceCode1 = codeArray[0];
            //先确定给这个企业匹配什么语言的套餐
            String languageType = assistService.queryLanguageType(request.getPartnerCode(), request.getLanguageCode());

            // 根据partnerIndex分别去分库里面取相应的卡片与套餐对应关系的数据：
            Integer partnerIndex = Integer.parseInt(partnerService.getPartnerIndex(request.getPartnerCode()));

            if (StringUtils.isBlank(languageType) || null == partnerIndex) {
                log.info("languageType查询失误或者partnerIndex查询有误");
                return ResultDataDto.addOperationFailure(msg.getResException());
            }

            //走这里去匹配卡拿套餐了
            List<PartnerServicePlan> planList = assistService.queryServicePlanCode(partnerIndex, request.getPartnerCode(), deviceCode1, languageType, "0");

            //如果没有匹配到套餐列表，直接返回Not Service Plan
            if (null == planList || planList.isEmpty()) {
                log.info("Multiple模式未匹配到套餐,Not Service Plan");
                return ResultDataDto.addOperationFailure(msg.getNotInUseService());
            }
            if (codeArray.length > 1) {
                //验证Multiple多卡请求可购买套餐列表的时候的iccId集合
                for (String code : codeArray) {
                    if (StringUtils.isBlank(code)) {
                        log.info("deviceCode参数可能为空或者没传");
                        return ResultDataDto.addOperationFailure(msg.getResPartnerException());
                    }
                    //1，走这里去匹配卡拿套餐了
                    List<PartnerServicePlan> planList2 = assistService.queryServicePlanCode(partnerIndex, request.getPartnerCode(), code, languageType, "0");
                    //如果没有匹配到套餐列表，直接返回Not Service Plan
                    if (null == planList2 || planList2.isEmpty()) {
                        log.info("Multiple模式未匹配到套餐,Not Service Plan");
                        return ResultDataDto.addOperationFailure(msg.getNotInUseService());
                    }
                    //用第一张卡匹配到的套餐来跟循环里面的套餐列表比对，一旦不一样马上返回
                    if (!planList.equals(planList2)) {
                        log.info("Multiple模式：可够套餐列表不一致");
                        return ResultDataDto.addOperationFailure(msg.getDifferentPartnerCard());
                    }
                }
            }
            //走到这边说明套餐列表是一致的，遍历一个planList就可以了
            return assistService.responseServicePlan(planList, request.getPartnerCode(), "0");

        } catch (Exception e) {
            log.info("deviceCode参数传递有误");
            return ResultDataDto.addOperationFailure(msg.getResPartnerException());
        }
    }

    /**
     * Multiple模式卡片：下单接口
     * <p>
     * 返回格式是：{"data":{},"message":"string","operateCode":"string"},ResponseMultipleOrder是data部分
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto multipleOrder(RequestMultipleOrder request) {
        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);
        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【Multiple模式：下单】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getPayId()) || StringUtils.isBlank(request.getPayAmount()) || StringUtils.isBlank(request.getPayCurrency()) ||
                StringUtils.isBlank(request.getPackageCode()) || StringUtils.isBlank(request.getServicePlanCode()) || StringUtils.isBlank(request.getServicePlanShowName()) || StringUtils.isBlank(request.getOrderPeriod()) ||
                null == request.getRequestOrderId() || StringUtils.isBlank(request.getOrderList()) || StringUtils.isBlank(request.getAutoRenewal())) {
            log.info("【Multiple模式：下单】请求不合法：" + JSON.toJSONString(ResultDataDto.addOperationFailure(msg.getInvalidParam())));
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }

        /*先判断统一处理的结果*/
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }

        /*不归属领科的卡片不允许做小批量操作*/
        if (StringOutputConstant.CODE_ONE.equals(request.getMark())) {
            log.info("Multiple下单失败：不归属领科的卡片不允许做小批量操作提示：无效卡片返回");
            return ResultDataDto.addOperationFailure(msg.getInvalidCard());
        }

        /*验证一下前端传上来的金额是不是符合规则的*/
        boolean bVerify = !ParameterValidationUtil.isPositive(request.getPayAmount()) || (!"USD".equalsIgnoreCase(request.getPayCurrency()) && !"CNY".equalsIgnoreCase(request.getPayCurrency()) && !"EUR".equalsIgnoreCase(request.getPayCurrency()));
        if (bVerify) {
            log.info("Multiple下单失败：payAmount支付金额或者payCurrency不符合规则");
            return ResultDataDto.addOperationFailure(msg.getInvalidAmount());
        }
        /*现在用对象去把json字符拿出来*/
        List<MultipleDeviceOrder> orderList = null;
        try {
            //现在用对象去把json字符拿出来
            orderList = JSON.parseArray(request.getOrderList(), MultipleDeviceOrder.class);
        } catch (Exception e) {
            log.info("Multiple下单失败：下单orderList集合解析有异常");
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        /*第一遍循环遍历看看请求的设备iccId和orderNo是否存在为空的参数*/
        List<String> list0 = new ArrayList<>();
        List<String> list1 = new ArrayList<>();

        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode;

        for (MultipleDeviceOrder order : orderList) {
            deviceCode = order.getDeviceCode().replaceAll("\\s*", "");
            if (StringUtils.isNotBlank(deviceCode) && StringUtils.isNotBlank(order.getOrderNo())) {
                //先做下重复请求验证，对于同一个卡片deviceCode同一个套餐packageCode+servicePlanCode，同一个支付单号payId，同一个orderNo我们认为是唯一的请求，不同的请求支付单号必须刷新
                Integer count = logicMapper.queryOrderCount(request.getPartnerCode(), deviceCode, request.getPackageCode(), request.getServicePlanCode(), request.getPayId(), order.getOrderNo());
                if (count > 0) {
                    log.info("Multiple下单失败：重复的下单请求");
                    return ResultDataDto.addOperationFailure(msg.getRepeatOrder());
                }
                //如果不是重复往集合里面添加一个值
                list0.add("0");
            } else {
                list1.add("1");
            }
        }

        //list0>=1并且list1<1 才能允许继续往下
        boolean b1 = !list0.isEmpty() && list1.isEmpty();
        if (!b1) {
            log.info("Multiple下单失败：orderList存在不该为空的参数");
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        /*根据已有的企业和套餐编码去查询原始套餐表，确认套餐信息无误*/
        PartnerPackage packages = logicMapper.queryPackage(request.getPartnerCode(), request.getPackageCode());
        if (null == packages) {
            log.info("Multiple下单失败：企业下面不存在此原始套餐，或者请求内参数有误！");
            return ResultDataDto.addOperationFailure(msg.getNoRightOrder());
        }

        /*遍历原始套餐信息,把原始套餐的信息取出来用于订单入库时使用*/
        String partnerName = packages.getPartnerName();
        String packageName = packages.getPackageName();
        String packageType = packages.getPackageType();

        /*,这边要重点验证一下orderPeriod的值，只能是大于1的正整数,当套餐的最小可够数值和最大可够数值相等时，orderPeriod不等于这个值的时候*/
        boolean b4 = (!ParameterValidationUtil.isInteger(request.getOrderPeriod())) || (packages.getMinOrderPeriod().equals(packages.getMaxOrderPeriod()) && !request.getOrderPeriod().equals(packages.getMinOrderPeriod()));
        if (b4) {
            log.info("Multiple下单失败：orderPeriod订购周期不符合规则");
            return ResultDataDto.addOperationFailure(msg.getInvalidOrderPeriod());
        }

        /*比较一下下单请求中的servicePlanCode与orderPeriod和autoRenewal是否匹配，匹配就用传的值，不匹配就直接不让下单了，这样能保证用户始终能正常订购到我们发布的产品订购周期*/
        PartnerServicePlanSpecPrice specPrice = logicMapper.querySpecPricedByServicePlanCode(request.getServicePlanCode(), request.getOrderPeriod(), request.getAutoRenewal());
        if (null == specPrice) {
            log.info("Single下单失败：下单的servicePlanCode与specifications和autoRenewal查不到对应的价格方案");
            return ResultDataDto.addOperationFailure(msg.getFailedOrder());
        }
        if (!request.getServicePlanShowName().equals(specPrice.getServicePlanShowName())) {
            log.info("Single下单失败：下单的servicePlanShowName的传值与价格方案中不一致");
            return ResultDataDto.addOperationFailure(msg.getFailedOrder());
        }

        /*遍历出deviceCode和orderNo入库*/
        List<String> list2 = new ArrayList<>();
        List<String> list3 = new ArrayList<>();

        for (MultipleDeviceOrder order : orderList) {
            String code = order.getDeviceCode().replaceAll("\\s*", "");
            /*验证deviceCode卡片的有效性*/
            String result = assistService.validationDeviceCode(code, msg);
            if (!StringOutputConstant.CODE_SUCCESS.equalsIgnoreCase(result)) {
                return ResultDataDto.addOperationFailure(result);
            }
            /*卡片验证成功:验证流程结束，现在可以确定当前卡片是有效的，订单请求也没有重复，现在开始在数据库下单*/
            ServicePlanOrderRecord record = new ServicePlanOrderRecord();
            record.setPayId(request.getPayId());
            record.setRequestOrderId(request.getRequestOrderId());
            record.setDeviceCode(code);
            record.setOrderNo(order.getOrderNo());
            record.setPartnerCode(request.getPartnerCode());
            record.setPartnerName(partnerName);
            record.setServicePlanShowName(request.getServicePlanShowName());
            record.setServicePlanCode(request.getServicePlanCode());
            record.setPackageName(packageName);
            record.setPackageCode(request.getPackageCode());
            record.setPackageType(packageType);
            record.setOrderPeriod(request.getOrderPeriod());
            record.setPayAmount(request.getPayAmount());
            record.setPayCurrency(request.getPayCurrency());
            record.setTerminal(request.getTerminal());
            record.setMark(request.getMark());
            record.setPayMode(request.getAutoRenewal());

            Integer co = logicMapper.buildOrderRecord(record);
            if (co > 0) {
                list2.add("0");
            } else {
                list3.add("1");
            }
        }
        /*list0>=1并且list1<1 才能允许继续往下*/
        boolean b2 = !list2.isEmpty() && list3.isEmpty();
        if (!b2) {
            log.info("Multiple下单失败:数据入数据库失败");
            return ResultDataDto.addOperationFailure(msg.getFailedOrder());
        }

        //成功下单返回：
        ResponseMultipleOrder response = new ResponseMultipleOrder();
        response.setPartnerCode(request.getPartnerCode());
        response.setPayId(request.getPayId());
        log.info("【Multiple模式下单】成功响应：" + JSON.toJSONString(response));
        return ResultDataDto.addOperationSuccess().setData(response);
    }

    /**
     * 是否已经邮箱订阅?
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto mailSubscribedOrNot(RequestMailSubscribedOrNot request) {

        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg("1");

        if (null == request || StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }

        log.info("【是否订阅？】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode())) {
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }
        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }

        //先判断统一处理的结果：
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }

        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");

        try {
            //将字符串用逗号分隔开
            String[] codeArray = deviceCode.split(",");

            //验证请求的deviceCode是否存在不合法
            List<String> list0 = new ArrayList<>();
            List<String> list1 = new ArrayList<>();

            for (String code : codeArray) {

                //首先判断deviceCode存不存在为空的情况
                if (StringUtils.isBlank(code)) {
                    log.info("deviceCode参数可能为空或者没传");
                    return ResultDataDto.addOperationFailure(msg.getResPartnerException());
                }

                //查询卡片是否已经订阅过
                Integer c = logicMapper.querySubscribedOrNot(request.getPartnerCode(), code);
                if (c >= 1) {
                    list1.add("0");
                } else {
                    list0.add("0");
                }
            }

            //下面来做是否订阅的返回
            ResponseMailSubscribedOrNot response = new ResponseMailSubscribedOrNot();
            if (!list1.isEmpty()) {
                //已经订阅过，至少有一张卡曾经订阅过
                response.setSubscribeStatus("1");
            } else {
                //未订阅过
                response.setSubscribeStatus("0");
            }
            response.setPartnerCode(request.getPartnerCode());
            log.info("【是否订阅？】成功响应：" + JSON.toJSONString(response));
            return ResultDataDto.addOperationSuccess().setData(response);

        } catch (Exception e) {
            log.info("deviceCode参数传递有误");
            return ResultDataDto.addOperationFailure(msg.getResPartnerException());
        }
    }

    /**
     * 邮件订阅
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto mailSubscribe(RequestMailSubscribe request) {

        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg("1");

        if (null == request || StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }

        log.info("【订阅】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getLanguageCode()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getPayId()) ||
                StringUtils.isBlank(request.getEmailCode()) || StringUtils.isBlank(request.getSubmitType()) || null == request.getTroubleText() || StringUtils.isBlank(request.getDeviceCode())) {
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }
        //先判断统一处理的结果：
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }

        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");

        try {
            //将字符串用逗号分隔开
            String[] codeArray = deviceCode.split(",");
            //验证请求的deviceCode是否存在不合法
            for (String code : codeArray) {
                //首先判断deviceCode存不存在为空的情况
                if (StringUtils.isBlank(code)) {
                    log.info("deviceCode参数可能为空或者没传");
                    return ResultDataDto.addOperationFailure(msg.getResPartnerException());
                }
            }
            //开始判断提交类型：1-订阅；2-异常信息提交
            for (String code : codeArray) {
                Integer c = 0;
                if ("1".equals(request.getSubmitType())) {
                    //查询卡片是否已经订阅过 1，订阅一个iccid只允许订阅一次，仅能绑定一个邮箱；已经订阅的用户不允许在前端再显示订阅窗口。
                    c = logicMapper.querySubscribedOrNot(request.getPartnerCode(), code);
                }
                //允许入库：
                if (c <= 0 || "1".equals(request.getSubmitType())) {
                    //1，未订阅过或者异常信息提交：2，异常信息允许同个iccid重复，多次提交；前后端都不做控制。
                    UserEmailAndDeviceSubscribeInfo info = new UserEmailAndDeviceSubscribeInfo();
                    info.setSubmitType(request.getSubmitType());
                    info.setPartnerCode(request.getPartnerCode());
                    info.setDeviceCode(code);
                    info.setEmailCode(request.getEmailCode());
                    info.setPayId(request.getPayId());
                    info.setTroubleText(request.getTroubleText());
                    logicMapper.insertSubscribeInfo(info);
                }
            }
            log.info("【订阅】成功响应：" + JSON.toJSONString(ResultDataDto.addOperationSuccess()));
            return ResultDataDto.addOperationSuccess();

        } catch (Exception e) {
            log.info("deviceCode参数传递有误");
            return ResultDataDto.addOperationFailure(msg.getResPartnerException());
        }
    }

    /**
     * Single模式：查询自动续费记录
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto queryAutoRenewalRecord(RequestQueryAutoRenewalRecord request) {
        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【查询自动续费记录】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getLanguageCode()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode())) {
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }
        //先判断统一处理的结果：
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }
        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");
        List<ResponseQueryAutoRenewalRecord> response = new ArrayList<>();
        //先去自动续费记录表中查一下有没有记录
        List<ServicePlanOrderAutoRenewalRecord> recordList = logicMapper.queryAutoRenewalRecord(request.getPartnerCode(), deviceCode);
        if (null == recordList || recordList.isEmpty()) {
            //说明卡片直接就没有自动续费的记录，直接返回
            log.info("卡片没有自动续费记录");
            return ResultDataDto.addOperationSuccess(msg.getNoAutoRecord()).setData(response);
        }
        /*有记录*/
        for (ServicePlanOrderAutoRenewalRecord auto : recordList) {
            ServicePlanOrderRecord record = logicMapper.queryOrderRecord(auto.getPayId());
            if (null != record) {
                ResponseQueryAutoRenewalRecord rec = new ResponseQueryAutoRenewalRecord();
                rec.setPartnerCode(record.getPartnerCode());
                rec.setDeviceCode(deviceCode);
                rec.setPayId(record.getPayId());
                rec.setOrderNo(record.getOrderNo());
                rec.setServicePlanShowName(record.getServicePlanShowName());
                rec.setOrderPeriod(record.getOrderPeriod());
                rec.setPackageType(record.getPackageType());
                try {
                    if (StringUtils.isNotBlank(record.getPayResultDate())) {
                        /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                        df.setLenient(false);
                        rec.setSubscriptionTime(new SimpleDateFormat("yyyy.MM.dd").format(df.parse(record.getPayResultDate())));
                    } else {
                        rec.setSubscriptionTime("-");
                    }
                } catch (Exception e) {
                    log.info("订阅时间解析有误：" + e);
                    rec.setSubscriptionTime("-");
                }
                response.add(rec);
            }
        }
        log.info("【查询自动续费记录】成功响应：" + JSON.toJSONString(response));
        return ResultDataDto.addOperationSuccess().setData(response);
    }

    /**
     * Single模式：取消自动续费的原因
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto reasonForCancel(RequestReasonForCancel request) {
        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        /*去数据库取多语言错误的提示信息*/
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【取消自动续费服务的原因】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getLanguageCode()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode()) ||
                StringUtils.isBlank(request.getPayId()) || StringUtils.isBlank(request.getReasons())) {
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }
        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }
        /*先判断统一处理的结果*/
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }
        /*格式化一下iccId，去掉所有的空格，首和尾以及中间*/
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");
        /*去数据表拿到想要取消自动续费（服务）的记录，以便存起来*/
        ServicePlanOrderAutoRenewalRecord record = logicMapper.queryAutoRecord(request.getPartnerCode(), deviceCode, request.getPayId());
        if (null == record) {
            //说明卡片直接就没有自动续费的记录，直接返回
            log.info(deviceCode + "：无自动续费服务，无需取消");
            return ResultDataDto.addOperationFailure(msg.getNoAutoRecord());
        }
        /*去数据表中存储取消自动续费的服务和原因*/
        PartnerReasonForCancelRecord reason = PartnerReasonForCancelRecord.builder()
                .partnerCode(request.getPartnerCode()).deviceCode(deviceCode).payId(request.getPayId())
                .planId(record.getPlanId()).pmId(record.getPmId()).subId(record.getSubId()).customerId(record.getCustomerId())
                .terminal(request.getTerminal()).mark(request.getMark()).languageCode(request.getLanguageCode()).reasons(request.getReasons())
                .build();
        Integer count = logicMapper.insertReasonForCancelRecord(reason);
        if (count > 0) {
            log.info("【取消自动续费服务的原因】记录成功");
        }
        /*最终都要响应成功*/
        return ResultDataDto.addOperationSuccess();
    }

    /**
     * Single模式：：取消自动续费记录
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto cancelAutoRenewalRecord(RequestCancelAutoRenewalRecord request) {
        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        //去数据库取多语言错误的提示信息
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【取消自动续费记录】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getLanguageCode()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode()) ||
                StringUtils.isBlank(request.getPayId()) || StringUtils.isBlank(request.getOrderNo())) {
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }
        //先判断统一处理的结果：
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }
        //格式化一下iccId，去掉所有的空格，首和尾以及中间
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");
        //拿到取消自动续费记录所需要的记录
        ServicePlanOrderAutoRenewalRecord record = logicMapper.queryAutoRecord(request.getPartnerCode(), deviceCode, request.getPayId());
        if (null == record) {
            //说明卡片直接就没有自动续费的记录，直接返回
            log.info("【取消自动续费记录】无自动续费的记录");
            return ResultDataDto.addOperationFailure(msg.getNoAutoRecord());
        }
        //去支付网关取消自动续费记录
        ResultDataDto dto = toGatewayService.stripeSubCancel(record);
        if (dto.getOperateCode().equals(StringOutputConstant.CODE_F) || null == dto.getData()) {
            //说明卡片直接就没有自动续费的记录，直接返回
            log.info("【取消自动续费记录】失败");
            return ResultDataDto.addOperationFailure(msg.getFailedToUnSub());
        }
        log.info("【取消自动续费记录】成功响应：" + JSON.toJSONString(dto.getData()));
        return ResultDataDto.addOperationSuccess().setData(dto.getData());
    }

    /**
     * Single模式：用户支付完成后:点击礼物盒的记录
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto clickGiftBox(RequestClickGiftBox request) {
        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        /*去数据库取多语言错误的提示信息*/
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【点击礼物盒】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getLanguageCode()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode()) ||
                StringUtils.isBlank(request.getPayId())) {
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }
        /*先判断统一处理的结果*/
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }
        /*把点击礼物盒的记录存到数据表去就可以*/
        PartnerGiftBoxClickRecord giftBoxClick = PartnerGiftBoxClickRecord.builder()
                .partnerCode(request.getPartnerCode()).deviceCode(request.getDeviceCode().replaceAll("\\s*", ""))
                .payId(request.getPayId().replaceAll("\\s*", "")).terminal(request.getTerminal())
                .mark(request.getMark()).languageCode(request.getLanguageCode())
                .build();
        Integer count = logicMapper.insertGiftBoxClickRecord(giftBoxClick);
        if (count > 0) {
            /*直接响应成功就可以了*/
            log.info("【点击礼物盒】成功响应");
        }
        /*最终都要响应成功*/
        return ResultDataDto.addOperationSuccess();
    }

    /**
     * Single模式：：用户"My Order" 获取卡片所有的购买交易记录
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto myTransactionHistory(RequestMyTransactionHistory request) {
        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        /*去数据库取多语言错误的提示信息*/
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【我的交易记录】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getLanguageCode()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode())) {
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }
        /*先判断统一处理的结果*/
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }
        /*格式化一下iccId，去掉所有的空格，首和尾以及中间*/
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");

        List<ServicePlanOrderRecord> recordList = logicMapper.queryTransactionHistory(request.getPartnerCode(), deviceCode);
        List<ResponseMyTransactionHistory> response = new ArrayList<>();
        if (null != recordList && !recordList.isEmpty()) {
            for (ServicePlanOrderRecord record : recordList) {
                ResponseMyTransactionHistory history = new ResponseMyTransactionHistory();
                history.setServicePlanShowName(record.getServicePlanShowName());
                history.setPayType(record.getPayType());
                try {
                    if (StringUtils.isNotBlank(record.getPayResultDate())) {
                        /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                        df.setLenient(false);
                        history.setPayResultDate(new SimpleDateFormat("yyyy.MM.dd HH:mm").format(df.parse(record.getPayResultDate())));
                    } else {
                        history.setPayResultDate("-");
                    }
                } catch (Exception e) {
                    log.info("交易记录支付时间解析有误：" + e);
                    history.setPayResultDate("-");
                }
                history.setPayId(record.getPayId());
                if ("USD".equalsIgnoreCase(record.getPayCurrency())) {
                    history.setPayAmount("$" + record.getPayAmount());
                } else if ("EUR".equalsIgnoreCase(record.getPayCurrency())) {
                    history.setPayAmount("€" + record.getPayAmount());
                } else {
                    history.setPayAmount("￥" + record.getPayAmount());
                }
                history.setPayCurrency(record.getPayCurrency());
                response.add(history);
            }
        }
        /*如果没有查到对应的交易记录，那也要按照成功响应，不过data为空数组"data": []*/
        /*不管查没查到交易记录都要成功返回*/
        return ResultDataDto.addOperationSuccess().setData(response);
    }

    /**
     * Single模式：按不同状态（2-正在使用；1-未生效；3-已失效）查询订单
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDataDto queryOrdersByStatus(RequestQueryOrdersByStatus request) {
        String languageCode = "1";
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            languageCode = request.getLanguageCode();
        }
        /*去数据库取多语言错误的提示信息*/
        LangMultipleErrorMsg msg = assistService.getLangMultipleErrorMsg(languageCode);

        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            return ResultDataDto.addOperationFailure(msg.getRequestEmpty());
        }
        log.info("【按状态查询订单】请求：" + JSON.toJSONString(request));
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getTradeTime()) || StringUtils.isBlank(request.getVersion()) ||
                StringUtils.isBlank(request.getTerminal()) || StringUtils.isBlank(request.getMark()) || StringUtils.isBlank(request.getSign()) ||
                StringUtils.isBlank(request.getLanguageCode()) || StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode()) ||
                StringUtils.isBlank(request.getStatus())) {
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }

        String sign = Md5Encrypt.jsonSign(request);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return ResultDataDto.addOperationFailure(msg.getInvalidSign());
        }
        /*先判断统一处理的结果*/
        String re = assistService.unifiedHandling(request.getTerminal(), request.getMark(), msg.getInvalidTerminal(), msg.getInvalidMark());
        boolean b0 = StringOutputConstant.CODE_SUCCESS.equals(re);
        if (!b0) {
            return ResultDataDto.addOperationFailure(re);
        }
        /*status除了可以传1,2,3这三个值，其他的值都是不允许的*/
        if (!StringOutputConstant.CODE_ONE.equals(request.getStatus()) && !StringOutputConstant.CODE_TWO.equals(request.getStatus()) && !StringOutputConstant.CODE_THREE.equals(request.getStatus())) {
            log.info("status传值不符合实际情况：" + request.getStatus());
            return ResultDataDto.addOperationFailure(msg.getInvalidParam());
        }
        /*格式化一下iccId，去掉所有的空格，首和尾以及中间*/
        String deviceCode = request.getDeviceCode().replaceAll("\\s*", "");
        /*响应内容提前备好*/
        List<ResponseQueryOrdersByStatus> response = new ArrayList<>();
        /*归属领科卡片*/
        if (StringOutputConstant.CODE_ZERO.equalsIgnoreCase(request.getMark())) {
            //我们继续用获得的企业编码去做更多的查询
            String secret = partnerService.getSecretByPartnerCode(request.getPartnerCode());
            if (StringUtils.isBlank(secret)) {
                log.info("【按状态查询订单】" + request.getPartnerCode() + ";当前企业secret有误请联系管理员！");
                return ResultDataDto.addOperationFailure(msg.getInvalidSecret());
            }
            /*用3.0的查询订单的接口进行查询：按照1-未启用；2-正在使用；3-已结束的状态分别去查询订单*/
            ResponseQueryDeviceOrder order = toBeijingService.queryDeviceOrder(deviceCode, "", request.getStatus(), "", request.getPartnerCode(), secret);
            /*查询有结果的时候才分别去遍历，没有结果就是直接返回else，data就是空数组："data": []*/
            if (null != order && order.getData() != null && null != order.getData().getPackageOrder() && !order.getData().getPackageOrder().isEmpty()) {
                /*下面开始是分不同的状态响应不同的展示参数回去供前端显示*/
                if (StringOutputConstant.CODE_ONE.equals(request.getStatus())) {
                    for (com.vshop.entity.agatewaytobeijing.querydeviceorder.response.DevicePackageOrder data : order.getData().getPackageOrder()) {
                        /*拿着data.getPackageCode()去数据库：partner_package_not_show_t查询当前套餐需不需要展示*/
                        Integer c = logicMapper.queryPackageShowOrNot(request.getPartnerCode(), data.getPackageCode());
                        boolean b1 = c >= 1;
                        /*如果有存在订单的套餐是不需要展示给用户的，不去遍历*/
                        if (b1) {
                            continue;
                        }
                        ResponseQueryOrdersByStatus orders = new ResponseQueryOrdersByStatus();
                        orders.setStatus(request.getStatus());
                        try {
                            if (StringUtils.isNotBlank(data.getOrderDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                sdf.setLenient(false);
                                orders.setOrderDate(new SimpleDateFormat("yyyy.MM.dd").format(sdf.parse(data.getOrderDate())));
                            } else {
                                orders.setOrderDate("-");
                            }
                        } catch (Exception e) {
                            log.info("订购日期解析有误：" + e);
                            orders.setOrderDate("-");
                        }
                        response.add(orders);
                    }
                } else if (StringOutputConstant.CODE_TWO.equals(request.getStatus())) {
                    for (com.vshop.entity.agatewaytobeijing.querydeviceorder.response.DevicePackageOrder data : order.getData().getPackageOrder()) {
                        /*拿着data.getPackageCode()去数据库：partner_package_not_show_t查询当前套餐需不需要展示*/
                        Integer c = logicMapper.queryPackageShowOrNot(request.getPartnerCode(), data.getPackageCode());
                        boolean b1 = c >= 1;
                        /*如果有存在订单的套餐是不需要展示给用户的，不去遍历*/
                        if (b1) {
                            continue;
                        }
                        ResponseQueryOrdersByStatus orders = new ResponseQueryOrdersByStatus();
                        orders.setStatus(request.getStatus());
                        try {
                            if (StringUtils.isNotBlank(data.getExpireDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                sd.setLenient(false);
                                /*正在使用的订单的剩余天数=理论到期时间-今天*/
                                orders.setRemainingDays(DateUtil.remainingDays(sd.parse(data.getExpireDate()), "1"));
                            } else {
                                orders.setRemainingDays("-");
                            }
                        } catch (Exception e) {
                            log.info("计算理论到期天数解析有误：" + e);
                            orders.setRemainingDays("-");
                        }
                        try {
                            if (StringUtils.isNotBlank(data.getActiveDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                sd.setLenient(false);
                                orders.setActiveDate(new SimpleDateFormat("yyyy.MM.dd").format(sd.parse(data.getActiveDate())));
                            } else {
                                orders.setActiveDate("-");
                            }
                        } catch (Exception e) {
                            log.info("启用日期解析有误：" + e);
                            orders.setActiveDate("-");
                        }
                        try {
                            if (StringUtils.isNotBlank(data.getExpireDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                sd.setLenient(false);
                                orders.setExpireDate(new SimpleDateFormat("yyyy.MM.dd").format(sd.parse(data.getExpireDate())));
                            } else {
                                orders.setExpireDate("-");
                            }
                        } catch (Exception e) {
                            log.info("失效日期解析有误：" + e);
                            orders.setExpireDate("-");
                        }
                        response.add(orders);
                    }
                } else {
                    for (com.vshop.entity.agatewaytobeijing.querydeviceorder.response.DevicePackageOrder data : order.getData().getPackageOrder()) {
                        /*1，拿着data.getPackageCode()去数据库：partner_package_give_t查询是不是赠送套餐*/
                        Integer c = purchaseService.queryGiveDateOrNot(data.getPackageCode());
                        /*2，拿着data.getPackageCode()去数据库：partner_package_not_show_t查询当前套餐需不需要展示*/
                        Integer c1 = logicMapper.queryPackageShowOrNot(request.getPartnerCode(), data.getPackageCode());
                        boolean b1 = c >= 1;
                        boolean b2 = c1 >= 1;
                        /*如果有存在订单的套餐是赠送套餐，不去遍历*/
                        /*或者*/
                        /*如果有存在订单的套餐是不需要展示给用户的，不去遍历*/
                        if (b1 || b2) {
                            continue;
                        }
                        /*商用已结束套餐才展示：走到这边说明卡上上的已结束套餐肯定不是赠送套餐*/
                        ResponseQueryOrdersByStatus orders = new ResponseQueryOrdersByStatus();
                        orders.setStatus(request.getStatus());
                        try {
                            if (StringUtils.isNotBlank(data.getOrderDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                sdf.setLenient(false);
                                orders.setOrderDate(new SimpleDateFormat("yyyy.MM.dd").format(sdf.parse(data.getOrderDate())));
                            } else {
                                orders.setOrderDate("-");
                            }
                        } catch (Exception e) {
                            log.info("订购时间解析有误：" + e);
                            orders.setOrderDate("-");
                        }
                        try {
                            if (StringUtils.isNotBlank(data.getActiveDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                sd.setLenient(false);
                                orders.setActiveDate(new SimpleDateFormat("yyyy.MM.dd").format(sd.parse(data.getActiveDate())));
                            } else {
                                orders.setActiveDate("-");
                            }
                        } catch (Exception e) {
                            log.info("启用时间解析有误：" + e);
                            orders.setActiveDate("-");
                        }
                        try {
                            if (StringUtils.isNotBlank(data.getExpireDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                sd.setLenient(false);
                                orders.setExpireDate(new SimpleDateFormat("yyyy.MM.dd").format(sd.parse(data.getExpireDate())));
                            } else {
                                orders.setExpireDate("-");
                            }
                        } catch (Exception e) {
                            log.info("失效时间解析有误：" + e);
                            orders.setExpireDate("-");
                        }
                        response.add(orders);
                    }
                }
            }
        }
        /*非领科卡片直接查询我们自己的订单系统就够了*/
        if (StringOutputConstant.CODE_ONE.equalsIgnoreCase(request.getMark())) {
            List<PartnerSpecialDeviceLifecycle> recordList = logicMapper.querySpecialOrderByStatus(request.getPartnerCode(), deviceCode, request.getMark(), request.getStatus());
            /*查询有结果的时候才分别去遍历，没有结果就是直接返回else，data就是空数组："data": []*/
            if (null != recordList && !recordList.isEmpty()) {
                /*遍历特殊设备的生命周期订单：下面开始是分不同的状态响应不同的展示参数回去供前端显示*/
                if (StringOutputConstant.CODE_ONE.equals(request.getStatus())) {
                    for (PartnerSpecialDeviceLifecycle device : recordList) {
                        ResponseQueryOrdersByStatus orders = new ResponseQueryOrdersByStatus();
                        orders.setStatus(request.getStatus());
                        try {
                            if (StringUtils.isNotBlank(device.getOrderDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                df.setLenient(false);
                                orders.setOrderDate(new SimpleDateFormat("yyyy.MM.dd").format(df.parse(device.getOrderDate())));
                            } else {
                                orders.setOrderDate("-");
                            }
                        } catch (Exception e) {
                            log.info("非领科卡订购日期解析有误：" + e);
                            orders.setOrderDate("-");
                        }
                        response.add(orders);
                    }
                } else if (StringOutputConstant.CODE_TWO.equals(request.getStatus())) {
                    for (PartnerSpecialDeviceLifecycle device : recordList) {
                        ResponseQueryOrdersByStatus orders = new ResponseQueryOrdersByStatus();
                        orders.setStatus(request.getStatus());
                        try {
                            if (StringUtils.isNotBlank(device.getOrderExpireDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                df.setLenient(false);
                                /*正在使用的订单的剩余天数=理论到期时间-今天*/
                                orders.setRemainingDays(DateUtil.remainingDays(df.parse(device.getOrderExpireDate()), "2"));
                            } else {
                                orders.setRemainingDays("-");
                            }
                        } catch (Exception e) {
                            log.info("非领科卡计算理论到期天数解析有误：" + e);
                            orders.setRemainingDays("-");
                        }
                        try {
                            if (StringUtils.isNotBlank(device.getOrderStartDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                df.setLenient(false);
                                orders.setActiveDate(new SimpleDateFormat("yyyy.MM.dd").format(df.parse(device.getOrderStartDate())));
                            } else {
                                orders.setActiveDate("-");
                            }
                        } catch (Exception e) {
                            log.info("非领科卡启用日期解析有误：" + e);
                            orders.setActiveDate("-");
                        }
                        try {
                            if (StringUtils.isNotBlank(device.getOrderExpireDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                df.setLenient(false);
                                orders.setExpireDate(new SimpleDateFormat("yyyy.MM.dd").format(df.parse(device.getOrderExpireDate())));
                            } else {
                                orders.setExpireDate("-");
                            }
                        } catch (Exception e) {
                            log.info("非领科卡失效日期解析有误：" + e);
                            orders.setExpireDate("-");
                        }
                        response.add(orders);
                    }
                } else {
                    for (PartnerSpecialDeviceLifecycle device : recordList) {
                        ResponseQueryOrdersByStatus orders = new ResponseQueryOrdersByStatus();
                        orders.setStatus(request.getStatus());
                        try {
                            if (StringUtils.isNotBlank(device.getOrderDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                df.setLenient(false);
                                orders.setOrderDate(new SimpleDateFormat("yyyy.MM.dd").format(df.parse(device.getOrderDate())));
                            } else {
                                orders.setOrderDate("-");
                            }
                        } catch (Exception e) {
                            log.info("非领科卡订购时间解析有误：" + e);
                            orders.setOrderDate("-");
                        }
                        try {
                            if (StringUtils.isNotBlank(device.getOrderStartDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                df.setLenient(false);
                                orders.setActiveDate(new SimpleDateFormat("yyyy.MM.dd").format(df.parse(device.getOrderStartDate())));
                            } else {
                                orders.setActiveDate("-");
                            }
                        } catch (Exception e) {
                            log.info("非领科卡启用时间解析有误：" + e);
                            orders.setActiveDate("-");
                        }
                        try {
                            if (StringUtils.isNotBlank(device.getOrderExpireDate())) {
                                /*SimpleDateFormat严格限制日期转换setLenient(false)*/
                                df.setLenient(false);
                                orders.setExpireDate(new SimpleDateFormat("yyyy.MM.dd").format(df.parse(device.getOrderExpireDate())));
                            } else {
                                orders.setExpireDate("-");
                            }
                        } catch (Exception e) {
                            log.info("非领科卡失效时间解析有误：" + e);
                            orders.setExpireDate("-");
                        }
                        response.add(orders);
                    }
                }
            }
        }
        /*成功响应*/
        log.info("【按状态查询订单】响应：" + JSON.toJSONString(response));
        return ResultDataDto.addOperationSuccess().setData(response);
    }

}
